package com.quick.proxy.server;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import com.quick.proxy.core.ChannelAttribute;
import com.quick.proxy.core.ChannelConstants;
import com.quick.proxy.core.CmdTypeConstants;
import com.quick.proxy.core.pojo.ProxyMapping;
import com.quick.proxy.core.utils.ProxyUtils;
import com.quick.proxy.core.utils.ResponseUtils;
import com.quick.proxy.server.event.VisitorProxyServerCreateEvent;
import com.quick.proxy.server.handler.visitor.VisitorProxyServerChildChannelHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * Description: 事件监听
 * Author: Administrator
 * Date: 2023/7/6
 *
 * @author 吃素不吃肉
 */
@Component
@Slf4j
public class ProxyEventListener {
    @Autowired
    private VisitorProxyServerChildChannelHandler visitorProxyServerChildChannelHandler;

    @EventListener
    public void visitorProxyServerCreateEvent(VisitorProxyServerCreateEvent visitorProxyServerCreateEvent) {
        List<ProxyMapping> accessKeyProxyMapping = visitorProxyServerCreateEvent.getAccessKeyProxyMapping();
        ChannelHandlerContext ctx = visitorProxyServerCreateEvent.getCtx();
        String accessKey = visitorProxyServerCreateEvent.getAccessKey();
        if (!CollectionUtils.isEmpty(accessKeyProxyMapping)) {
            for (ProxyMapping proxyMapping : accessKeyProxyMapping) {
                Channel proxyChannel = ChannelConstants.MAPPING_PORT_PROXY_CHANNEL.get(proxyMapping.getMappingPort());
                if (proxyChannel != null) {
                    String usedAccessKey = proxyChannel.attr(ChannelAttribute.ACCESS_KEY_PROXY_CHANNEL).get();
                    ResponseUtils.fail(ctx.channel(), CmdTypeConstants.AUTH, StrUtil.format("accessKey [{}] visitor server port {} is already in use", accessKey, proxyMapping.getMappingPort()));
                    log.warn("accessKey[{}] visitor server port {} is already in use by {}", accessKey, proxyMapping.getMappingPort(), usedAccessKey);
                    return;
                }
                log.info("[{}]Mapping Address {}:{}->{}", accessKey, ProxyUtils.getLocalAddress(), proxyMapping.getMappingPort(), proxyMapping.getRealProxyClientAddress());
                //启动访问者服务端
                ThreadUtil.execute(() -> ProxyUtils.createVisitorProxyServer(ctx.channel(), proxyMapping.getRealProxyClientAddress(), proxyMapping.getMappingPort(), visitorProxyServerChildChannelHandler));
            }
        } else {
            log.warn("accessKey [{}] not found proxy mapping list", accessKey);
        }
    }
}
